#include <windows.h>

#include "gps.h"

#include <service.h>

static HANDLE gpsHandle = NULL;
static HANDLE newLocationHandle;
static HANDLE deviceStateChangedHandle;

// Opens the GPS device and prepares to receive data from it.
void GPS_Open()
{
	if (gpsHandle == NULL)
	{
		newLocationHandle = CreateEvent(NULL, 0, 0, NULL);
		deviceStateChangedHandle = CreateEvent(NULL, 0, 0, NULL);

		gpsHandle = GPSOpenDevice(newLocationHandle, deviceStateChangedHandle, NULL, 0);
	}
}

void GPS_Close()
{
	if (gpsHandle != NULL)
	{
		GPSCloseDevice(gpsHandle);
		gpsHandle = NULL;

		CloseHandle(newLocationHandle);
		newLocationHandle = NULL;

		CloseHandle(deviceStateChangedHandle);
		deviceStateChangedHandle = NULL;
	}
}

BOOL GPS_IsOpened()
{
	return (gpsHandle != NULL);
}

BOOL GPS_DataHasChanged()
{
	HANDLE events[2] = {newLocationHandle, deviceStateChangedHandle};
	if (gpsHandle)
		return (WaitForMultipleObjects(2, events, FALSE, 0) != WAIT_TIMEOUT);
	else
		return FALSE;
}

void GPS_GetData(GPS_POSITION * pGPSPosition, GPS_DEVICE * pGPSDevice)
{
	if (pGPSPosition)
	{
		memset(pGPSPosition, 0, sizeof(GPS_POSITION));
		pGPSPosition->dwVersion = GPS_VERSION_CURRENT;
		pGPSPosition->dwSize = sizeof(GPS_POSITION);

		if (gpsHandle)
		{
			GPSGetPosition(gpsHandle, pGPSPosition, 500000, 0);
		}
	}

	if (pGPSDevice)
	{
		memset(pGPSDevice, 0, sizeof(GPS_DEVICE));
		pGPSDevice->dwVersion = GPS_VERSION_CURRENT;
		pGPSDevice->dwSize = sizeof(GPS_DEVICE);
	
		if (gpsHandle)
		{
			GPSGetDeviceState(pGPSDevice);
		}
	}
}

WCHAR * GPS_GetServiceStateDescription(DWORD serviceState)
{
	switch (serviceState)
	{
	case SERVICE_STATE_OFF:
		return L"Off";

	case SERVICE_STATE_ON:
		return L"On";

	case SERVICE_STATE_STARTING_UP:
		return L"StartingUp";

	case SERVICE_STATE_SHUTTING_DOWN:
		return L"ShuttingDown";

	case SERVICE_STATE_UNLOADING:
		return L"Unloading";

	case SERVICE_STATE_UNINITIALIZED:
		return L"Uninitialized";

	case SERVICE_STATE_UNKNOWN:
	default:
		return L"Unknown";
	}
}

void GPS_FormatDegreesMinutesSeconds(WCHAR * pszBuffer, double decimalDegrees)
{
	int degrees = (int) abs((int)decimalDegrees);
	double doubleMinutes = (fabsf((float)decimalDegrees) - fabsf((float)degrees)) * 60.0;
	int minutes = (int) doubleMinutes;
	double seconds = (doubleMinutes - (double)minutes) * 60.0;

	swprintf(pszBuffer, L"%dd %d' %f\"", degrees, minutes, seconds);
}
